home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / othergnu / gnuchess.zoo / UXDSP.C < prev   
Encoding:
C/C++ Source or Header  |  1988-08-09  |  24.0 KB  |  961 lines

  1. /*
  2.   ALPHA interface for CHESS
  3.    
  4.   Revision: 4-25-88
  5.    
  6.   Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
  7.   Copyright (c) 1988  John Stanback
  8.  
  9.   This file is part of CHESS.
  10.  
  11.   CHESS is distributed in the hope that it will be useful,
  12.   but WITHOUT ANY WARRANTY.  No author or distributor
  13.   accepts responsibility to anyone for the consequences of using it
  14.   or for whether it serves any particular purpose or works at all,
  15.   unless he says so in writing.  Refer to the CHESS General Public
  16.   License for full details.
  17.  
  18.   Everyone is granted permission to copy, modify and redistribute
  19.   CHESS, but only under the conditions described in the
  20.   CHESS General Public License.   A copy of this license is
  21.   supposed to have been given to you along with CHESS so you
  22.   can know your rights and responsibilities.  It should be in a
  23.   file named COPYING.  Among other things, the copyright notice
  24.   and this notice must be preserved on all copies.
  25. */
  26. /*
  27.   minor addition to the help screen by Bill Randle, 6-10-88
  28. */
  29. /*
  30.   modified to compile on the Atari ST under Megamax Laser C by Eric R. Smith
  31.   Aug 9, 1988
  32. */
  33.  
  34. #include <stdio.h>
  35. #include <ctype.h>
  36. #ifdef MEGAMAX
  37. # include "curses.h"
  38. # define W_OK 0
  39. # define signal(x,y)
  40.     extern long time();
  41. #else
  42. # include <sys/param.h>
  43. # include <sys/times.h>
  44. # include <sys/file.h>
  45. # include <curses.h>
  46. # include <signal.h>
  47. #endif MEGAMAX
  48. #include "gnuchess.h"
  49.  
  50. #ifndef MEGAMAX
  51. struct tms tmbuf1,tmbuf2;
  52. #endif
  53.  
  54. int TerminateSearch(),Die();
  55.  
  56. #define scanz fflush(stdout),scanw
  57. #define printz printw
  58.  
  59.  
  60. Initialize()
  61. {
  62.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  63.   initscr();
  64.   crmode();
  65. #ifdef MEGAMAX
  66.   nocrmode();
  67.   echo();
  68. #endif
  69. }
  70.  
  71.  
  72. ExitChess()
  73. {
  74.   nocrmode();
  75.   endwin();
  76.   exit(0);
  77. }
  78.  
  79. #ifndef MEGAMAX
  80. Die()
  81. {
  82. char s[80];
  83.   signal(SIGINT,SIG_IGN);
  84.   signal(SIGQUIT,SIG_IGN);
  85.   ShowMessage("Abort? ");
  86.   scanz("%s",s);
  87.   if (strcmp(s,"yes") == 0) ExitChess();
  88.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  89. }
  90.  
  91.  
  92. TerminateSearch()
  93. {
  94.   signal(SIGINT,SIG_IGN);
  95.   signal(SIGQUIT,SIG_IGN);
  96.   timeout = true;
  97.   bothsides = false;
  98.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  99. }
  100. #endif
  101.  
  102. InputCommand()
  103.  
  104. /*
  105.    Process the users command. If easy mode is OFF (the computer is 
  106.    thinking on opponents time) and the program is out of book, then make 
  107.    the 'hint' move on the board and call SelectMove() to find a response. 
  108.    The user terminates the search by entering ^C (quit siqnal) before 
  109.    entering a command. If the opponent does not make the hint move, then 
  110.    set Sdepth to zero. 
  111. */
  112.  
  113. {
  114. short ok,i,tmp;
  115. long cnt,rate,t1,t2;
  116. unsigned short mv;
  117. char s[80];
  118.  
  119.   ok = quit = false;
  120.   player = opponent;
  121.   ShowSidetomove();
  122.   ft = 0;
  123.   if (hint > 0 && !easy && Book == NULL)
  124.     {
  125.       fflush(stdout);
  126.       time0 = time((long *)0);
  127.       algbr(hint>>8,hint & 0xFF,false);
  128.       strcpy(s,mvstr1);
  129.       tmp = epsquare;
  130.       if (VerifyMove(s,1,&mv))
  131.         {
  132.           PromptForMove();
  133.           SelectMove(computer,2);
  134.           VerifyMove(mvstr1,2,&mv);
  135.           if (Sdepth > 0) Sdepth--;
  136.         }
  137.       ft = time((long *)0) - time0;
  138.       epsquare = tmp;
  139.     }
  140.   
  141.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  142.   while (!(ok || quit))
  143.     {
  144.       PromptForMove();
  145.       scanz("%s",s);
  146.       player = opponent;
  147.       ok = VerifyMove(s,0,&mv);
  148.       if (ok && mv != hint)
  149.         {
  150.           Sdepth = 0;
  151.           ft = 0;
  152.         }
  153.         
  154.       if (strcmp(s,"bd") == 0)
  155.         {
  156.           ClrScreen();
  157.           UpdateDisplay(0,0,1,0);
  158.         }
  159.       if (strcmp(s,"quit") == 0) quit = true;
  160.       if (strcmp(s,"post") == 0) post = !post;
  161.       if (strcmp(s,"edit") == 0) EditBoard();
  162.       if (strcmp(s,"go") == 0) ok = true;
  163.       if (strcmp(s,"help") == 0) help();
  164.       if (strcmp(s,"force") == 0) force = !force;
  165.       if (strcmp(s,"book") == 0) Book = NULL;
  166.       if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo();
  167.       if (strcmp(s,"new") == 0) NewGame();
  168.       if (strcmp(s,"list") == 0) ListGame();
  169.       if (strcmp(s,"level") == 0) SelectLevel();
  170.       if (strcmp(s,"hash") == 0) hashflag = !hashflag;
  171.       if (strcmp(s,"beep") == 0) beep = !beep;
  172.       if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow();
  173.       if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow();
  174.       if (strcmp(s,"hint") == 0) GiveHint();
  175.       if (strcmp(s,"both") == 0)
  176.         {
  177.           bothsides = !bothsides;
  178.           Sdepth = 0;
  179.           SelectMove(opponent,1);
  180.           ok = true;
  181.         }
  182.       if (strcmp(s,"reverse") == 0)
  183.         {
  184.           reverse = !reverse;
  185.           ClrScreen();
  186.           UpdateDisplay(0,0,1,0);
  187.         }
  188.       if (strcmp(s,"switch") == 0)
  189.         {
  190.           computer = otherside[computer];
  191.           opponent = otherside[opponent];
  192.           force = false;
  193.           Sdepth = 0;
  194.           ok = true;
  195.         }
  196.       if (strcmp(s,"white") == 0)  
  197.         {
  198.           computer = white; opponent = black;
  199.           ok = true; force = false;
  200.           Sdepth = 0;
  201.         }
  202.       if (strcmp(s,"black") == 0)
  203.         {
  204.           computer = black; opponent = white;
  205.           ok = true; force = false;
  206.           Sdepth = 0;
  207.         }
  208.       if (strcmp(s,"remove") == 0 && GameCnt >= 1) 
  209.         {
  210.           Undo(); Undo();
  211.         }
  212.       if (strcmp(s,"get") == 0) GetGame();
  213.       if (strcmp(s,"save") == 0) SaveGame();
  214.       if (strcmp(s,"depth") == 0) ChangeSearchDepth();
  215.       if (strcmp(s,"random") == 0) dither = 6;
  216.       if (strcmp(s,"easy") == 0) easy = !easy;
  217.       if (strcmp(s,"contempt") == 0) SetContempt();
  218.       if (strcmp(s,"xwndw") == 0) ChangeXwindow();
  219.       if (strcmp(s,"test") == 0)
  220.         {
  221.           t1 = time((long *)0);
  222.           cnt = 0;
  223.           for (i = 0; i < 10000; i++)
  224.             {
  225.               MoveList(opponent,2);
  226.               cnt += TrPnt[3] - TrPnt[2];
  227.             }
  228.           t2 = time((long *)0);
  229.           rate = cnt / (t2-t1);
  230.           gotoXY(50,24);
  231.           printz("cnt= %ld  rate= %ld",cnt,rate);
  232.           ClrEoln();
  233.         }
  234.       if (strcmp(s,"p") == 0) ShowPostnValues();
  235.       if (strcmp(s,"debug") == 0) DoDebug();
  236.     }
  237.     
  238.   ClearMessage();
  239.   ElapsedTime(1);
  240.   if (force)
  241.     {
  242.       computer = opponent; opponent = otherside[computer];
  243.     }
  244. #ifndef MEGAMAX
  245.   (void) times(&tmbuf1);
  246. #endif
  247.   signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch);
  248. }
  249.  
  250.  
  251. EditBoard()
  252.  
  253. /* 
  254.    Set up a board position. Pieces are entered by typing the piece 
  255.    followed by the location. For example, Nf3 will place a knight on 
  256.    square f3. 
  257. */
  258.  
  259. {
  260. short a,r,c,sq;
  261. char s[80];
  262.  
  263.   ClrScreen();
  264.   UpdateDisplay(0,0,1,0);
  265.   gotoXY(50,2); printz(".   Exit to main");
  266.   gotoXY(50,3); printz("#   Clear board");
  267.   gotoXY(49,5); printz("Enter piece & location: ");
  268.   a = white;
  269.   do
  270.   {
  271.     gotoXY(73,5); ClrEoln(); scanz("%s",s);
  272.     if (s[0] == '#')
  273.       {
  274.         for (sq = 0; sq < 64; sq++)
  275.           {
  276.             board[sq] = no_piece; color[sq] = neutral;
  277.           }
  278.         UpdateDisplay(0,0,1,0);
  279.       }
  280.     if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
  281.     c = s[1]-'a'; r = s[2]-'1';
  282.     if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
  283.       {
  284.         sq = locn[r][c];
  285.         color[sq] = a;
  286.         if (s[0] == 'p') board[sq] = pawn;
  287.         else if (s[0] == 'n') board[sq] = knight;
  288.         else if (s[0] == 'b') board[sq] = bishop;
  289.         else if (s[0] == 'r') board[sq] = rook;
  290.         else if (s[0] == 'q') board[sq] = queen;
  291.         else if (s[0] == 'k') board[sq] = king;
  292.         else { board[sq] = no_piece; color[sq] = neutral; }
  293.         DrawPiece(sq);
  294.       }
  295.   }
  296.   while (s[0] != '.');
  297.   if (board[4] != king) kingmoved[white] = 10;
  298.   if (board[60] != king) kingmoved[black] = 10;
  299.   GameCnt = -1; Game50 = 0; Sdepth = 0;
  300.   InitializeStats();
  301.   ClrScreen();
  302.   UpdateDisplay(0,0,1,0);
  303. }
  304.  
  305.  
  306. help()
  307. {
  308.   ClrScreen();
  309.   gotoXY(28,1); printz("CHESS command summary");
  310.   gotoXY(1,3); printz("g1f3      move from g1 to f3");
  311.   gotoXY(1,4); printz("nf3       move knight to f3");
  312.   gotoXY(1,5); printz("o-o       castle king side");
  313.   gotoXY(1,6); printz("o-o-o     castle queen side");
  314.   gotoXY(1,7); printz("edit      edit board");
  315.   gotoXY(1,8); printz("switch    sides with computer");
  316.   gotoXY(1,9); printz("white     computer plays white");
  317.   gotoXY(1,10); printz("black     computer plays black");
  318.   gotoXY(1,11); printz("reverse   board display");
  319.   gotoXY(1,12); printz("both      computer match");
  320.   gotoXY(1,13); printz("random    randomize play");
  321.   gotoXY(1,14); printz("undo      undo last move");
  322.   gotoXY(42,3); printz("level     change level");
  323.   gotoXY(42,4); printz("depth     set search depth");
  324.   gotoXY(42,5); printz("post      principle variation");
  325.   gotoXY(42,6); printz("hint      suggest a move");
  326.   gotoXY(42,7); printz("bd        redraw board");
  327.   gotoXY(42,8); printz("force     enter game moves");
  328.   gotoXY(42,9); printz("list      game to chess.lst");
  329.   gotoXY(42,10); printz("save      game to file");
  330.   gotoXY(42,11); printz("get       game from file");
  331.   gotoXY(42,12); printz("new       start new game");
  332.   gotoXY(42,13); printz("quit      exit CHESS");
  333.   gotoXY(10,21); printz("Computer: ");
  334.   if (computer == white) printz("WHITE"); else printz("BLACK");
  335.   gotoXY(10,22); printz("Opponent: ");
  336.   if (opponent == white) printz("WHITE"); else printz("BLACK");
  337.   gotoXY(10,23); printz("Level: %ld",Level);
  338.   gotoXY(10,24); printz("Easy mode: ");
  339.   if (easy) printz("ON"); else printz("OFF");
  340.   gotoXY(40,21); printz("Depth: %d",MaxSearchDepth);
  341.   gotoXY(40,22); printz("Random: "); 
  342.   if (dither) printz("ON"); else printz("OFF");
  343.   gotoXY(40,23); printz("Transposition table: ");
  344.   if (hashflag) printz("ON"); else printz("OFF");
  345.   gotoXY(40,24); printz("(press ESC to continue)");
  346.   refresh();
  347.   while (getch() != 27);
  348.   ClrScreen();
  349.   UpdateDisplay(0,0,1,0);
  350. }
  351.  
  352.  
  353. ShowDepth(ch)
  354. char ch;
  355. {
  356.   if (player == computer)
  357.     {
  358.       gotoXY(50,4); printz("Depth= %d%c ",Sdepth,ch); ClrEoln();
  359.     }
  360. }
  361.  
  362.  
  363. ShowResults(score,bstline,ch)
  364. short score;
  365. unsigned short bstline[];
  366. char ch;
  367. {
  368. short d,e,ply;
  369.   if (post && player == computer)
  370.     {
  371.       e = lpost;
  372.       gotoXY(50,5); printz("Score= %d",score); ClrEoln();
  373.       d = 8; gotoXY(50,d); ClrEoln();
  374.       for (ply = 1; bstline[ply] > 0; ply++)
  375.         {
  376.           algbr(bstline[ply] >> 8,bstline[ply] & 0xFF,false);
  377.           if (ply == 5 || ply == 9 || ply == 13 || ply == 17)
  378.             {
  379.               gotoXY(50,++d); ClrEoln();
  380.             }
  381.           printz("%5s ",mvstr1);
  382.         }
  383.       ClrEoln();
  384.       lpost = d;
  385.       while (++d <= e)
  386.         {
  387.           gotoXY(50,d); ClrEoln();
  388.         }
  389.     }
  390. }
  391.  
  392.  
  393. SearchStartStuff(side)
  394. short side;
  395. {
  396. short i;
  397.   signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch);
  398.   if (player == computer)
  399.     {
  400.       for (i = 5; i < 14; i++)
  401.         {
  402.           gotoXY(50,i); ClrEoln();
  403.         }
  404.       gotoXY(50,22); ClrEoln();
  405.       gotoXY(50,23); ClrEoln();
  406.     }
  407. }
  408.  
  409.  
  410. OutputMove()
  411. {
  412.   if (root->flags & epmask) UpdateDisplay(0,0,1,0);
  413.   else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask);
  414.   gotoXY(50,17); printz("My move is: %s",mvstr1);
  415.   if (beep) putchar(7);
  416.   ClrEoln();
  417.   
  418.   gotoXY(50,24);
  419.   if (root->flags & draw) printz("Draw game!");
  420.   else if (root->score == -9999) printz("opponent mates!");
  421.   else if (root->score == 9998) printz("computer mates!");
  422.   else if (root->score < -9000) printz("opponent will soon mate!");
  423.   else if (root->score > 9000)  printz("computer will soon mate!");
  424.   ClrEoln();
  425.   
  426.   if (post && player == computer)
  427.     {
  428.       gotoXY(50,22); printz("Nodes=   %6ld",NodeCnt); ClrEoln();
  429.       gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); ClrEoln();
  430.     }
  431. }
  432.  
  433.  
  434. ElapsedTime(iop)
  435.  
  436. /* 
  437.    Determine the time that has passed since the search was started. If 
  438.    the elapsed time exceeds the target (ResponseTime+ExtraTime) then set 
  439.    timeout to true which will terminate the search. 
  440. */
  441.  
  442. short iop;
  443. {
  444.   et = time((long *)0) - time0;
  445.   if (et < 0) et = 0;
  446.   ETnodes += 50;
  447.   if (et > et0 || iop == 1)
  448.     {
  449.       if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true;
  450.       et0 = et;
  451.       if (iop == 1)
  452.         {
  453.           time0 = time((long *)0); et0 = 0;
  454.         }
  455. #ifdef MEGAMAX
  456.       cputimer = 100*et;
  457.       if (et > 0) evrate = NodeCnt/(et+ft); else evrate = 0;
  458.       if (kbhit() && Sdepth > 1)
  459.         {
  460.           timeout = true;
  461.           bothsides = false;
  462.         }
  463. #else
  464.       (void) times(&tmbuf2);
  465.       cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ;
  466.       if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft);
  467.       else evrate = 0;
  468. #endif MEGAMAX
  469.       ETnodes = NodeCnt + 50;
  470.       UpdateClocks();
  471.     }
  472. }
  473.  
  474.  
  475. UpdateClocks()
  476. {
  477. short m,s;
  478.   m = et/60; s = (et - 60*m);
  479.   if (TCflag)
  480.     {
  481.       m = (TimeControl.clock[player] - et) / 60;
  482.       s = TimeControl.clock[player] - et - 60*m;
  483.     }
  484.   if (m < 0) m = 0;
  485.   if (s < 0) s = 0;
  486.   if (player == white)
  487.     if (reverse) gotoXY(20,2); else gotoXY(20,23);
  488.   else
  489.     if (reverse) gotoXY(20,23); else gotoXY(20,2);
  490.   printz("%d:%02d   ",m,s);
  491.   refresh();
  492. }
  493.  
  494.  
  495.  
  496. SetTimeControl()
  497. {
  498.   if (TCflag)
  499.     {
  500.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  501.       TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes;
  502.     }
  503.   else
  504.     {
  505.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  506.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  507.       Level = 60*(long)TCminutes;
  508.     }
  509.   et = 0;
  510.   ElapsedTime(1);
  511. }
  512.  
  513.  
  514. gotoXY(x,y)
  515. short x,y;
  516. {
  517.   move(y-1,x-1);
  518. }
  519.  
  520.  
  521. ClrScreen()
  522. {
  523.   clear(); refresh();
  524. }
  525.  
  526.  
  527. ClrEoln()
  528. {
  529.   clrtoeol(); refresh();
  530. }
  531.  
  532.  
  533. DrawPiece(sq)
  534. short sq;
  535. {
  536. short r,c; char x;
  537.   if (reverse) r = 7-row[sq]; else r = row[sq];
  538.   if (reverse) c = 7-column[sq]; else c = column[sq];
  539.   if (color[sq] == black) x = '*'; else x = ' ';
  540.   gotoXY(5+5*c,5+2*(7-r)); printz("%c%c",x,pxx[board[sq]]);
  541. }
  542.  
  543.  
  544. UpdateDisplay(f,t,flag,iscastle)
  545. short f,t,flag,iscastle;
  546. {
  547. short i,l,z; 
  548.   if (flag)
  549.     {
  550.       gotoXY(56,2); printz("CHESS");
  551.       i = 3;
  552.       gotoXY(3,++i);
  553.       printz("|----|----|----|----|----|----|----|----|");
  554.       while (i<19)
  555.         {
  556.           gotoXY(1,++i);
  557.           if (reverse) z = (i/2)-1; else z = 10-(i/2);
  558.           printz("%d |    |    |    |    |    |    |    |    |",z);
  559.           gotoXY(3,++i);
  560.           if (i < 19)
  561.             printz("+----+----+----+----+----+----+----+----+");
  562.         }
  563.       printz("|----|----|----|----|----|----|----|----|");
  564.       gotoXY(3,21);
  565.       if (reverse) printz("  h    g    f    e    d    c    b    a");
  566.               else printz("  a    b    c    d    e    f    g    h");
  567.       if (reverse) gotoXY(5,23); else gotoXY(5,2);
  568.       if (computer == black) printz("Computer"); else printz("Human   ");
  569.       if (reverse) gotoXY(5,2); else gotoXY(5,23);
  570.       if (computer == white) printz("Computer"); else printz("Human   ");
  571.       for (l = 0; l < 64; l++) DrawPiece(l);
  572.     }
  573.   else
  574.     {
  575.       DrawPiece(f); DrawPiece(t);
  576.       if (iscastle)
  577.         if (t > f)
  578.           { DrawPiece(f+3); DrawPiece(t-1); }
  579.         else
  580.           { DrawPiece(f-4); DrawPiece(t+1); }
  581.     }
  582.   refresh();
  583. }
  584.  
  585.  
  586. GetOpenings()
  587.  
  588. /*
  589.    Read in the Opening Book file and parse the algebraic notation for a 
  590.    move into an unsigned integer format indicating the from and to 
  591.    square. Create a linked list of opening lines of play, with 
  592.    entry->next pointing to the next line and entry->move pointing to a 
  593.    chunk of memory containing the moves. More Opening lines of up to 256 
  594.    half moves may be added to gnuchess.book. 
  595. */
  596.  
  597. {
  598. FILE *fd;
  599. int c,i,j,side;
  600. struct BookEntry *entry;
  601. unsigned short mv,*mp,tmp[100];
  602.  
  603.   if ((fd = fopen("gnuchess.book","r")) != NULL)
  604.     {
  605.       Book = NULL;
  606.       i = 0; side = white;
  607.       while ((c = parse(fd,&mv,side)) >= 0)
  608.         if (c == 1)
  609.           {
  610.             tmp[++i] = mv;
  611.             side = otherside[side];
  612.           }
  613.         else if (c == 0 && i > 0)
  614.           {
  615.             entry = (struct BookEntry *)malloc(sizeof(struct BookEntry));
  616.             mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short));
  617.             entry->mv = mp;
  618.             entry->next = Book;
  619.             Book = entry; 
  620.             for (j = 1; j <= i; j++) *(mp++) = tmp[j];
  621.             *mp = 0;
  622.             i = 0; side = white;
  623.           }
  624.       fclose(fd);
  625.     }
  626. }
  627.  
  628.  
  629. int parse(fd,mv,side)
  630. FILE *fd;
  631. unsigned short *mv;
  632. short side;
  633. {
  634. int c,i,r1,r2,c1,c2;
  635. char s[100];
  636.   while ((c = getc(fd)) == ' ');
  637.   i = 0; s[0] = c;
  638.   while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd);
  639.   s[++i] = '\0';
  640.   if (c == EOF) return(-1);
  641.   if (s[0] == '!' || i < 3)
  642.     {
  643.       while (c != '\n' && c != EOF) c = getc(fd);
  644.       return(0);
  645.     }
  646.   if (s[4] == 'o')
  647.     if (side == black) *mv = 0x3C3A; else *mv = 0x0402;
  648.   else if (s[0] == 'o')
  649.     if (side == black) *mv = 0x3C3E; else *mv = 0x0406;
  650.   else
  651.     {
  652.       c1 = s[0] - 'a'; r1 = s[1] - '1';
  653.       c2 = s[2] - 'a'; r2 = s[3] - '1';
  654.       *mv = (locn[r1][c1]<<8) + locn[r2][c2];
  655.     }
  656.   return(1);
  657. }
  658.  
  659.  
  660. GetGame()
  661. {
  662. FILE *fd;
  663. char fname[40];
  664. int c;
  665. short sq;
  666. unsigned short m;
  667.  
  668.   ShowMessage("File name: ");
  669.   scanz("%s",fname);
  670.   if (fname[0] == '\0') strcpy(fname,"chess.000");
  671.   if ((fd = fopen(fname,"r")) != NULL)
  672.     {
  673. /* modified for Laser C by ERS (%d in place of %hd, and spaces and newlines
  674. added) */
  675.       fscanf(fd,"%d %d %d\n",&computer,&opponent,&Game50);
  676.       fscanf(fd,"%d %d %d %d\n",
  677.              &castld[white],&castld[black],
  678.              &kingmoved[white],&kingmoved[black]);
  679.       fscanf(fd,"%d %d\n",&TCflag,&OperatorTime);
  680.       fscanf(fd,"%ld %ld %d %d\n",
  681.              &TimeControl.clock[white],&TimeControl.clock[black],
  682.              &TimeControl.moves[white],&TimeControl.moves[black]);
  683.       for (sq = 0; sq < 64; sq++)
  684.         {
  685.           fscanf(fd,"%d\n",&m);
  686.           board[sq] = (m >> 8); color[sq] = (m & 0xFF);
  687.           if (color[sq] == 0) color[sq] = neutral; else --color[sq];
  688.         }
  689.       GameCnt = -1; c = '?';
  690.       while (c != EOF)
  691.         {
  692.           ++GameCnt;
  693.           c = fscanf(fd,"%d %d %d %ld %d %d %d\n",&GameList[GameCnt].gmove,
  694.                      &GameList[GameCnt].score,&GameList[GameCnt].depth,
  695.                      &GameList[GameCnt].nodes,&GameList[GameCnt].time,
  696.                      &GameList[GameCnt].piece,&GameList[GameCnt].color);
  697.           if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral;
  698.           else --GameList[GameCnt].color;
  699.         }
  700.       GameCnt--;
  701.       if (TimeControl.clock[white] > 0) TCflag = true;
  702.       computer--; opponent--;
  703.     }
  704.   fclose(fd);
  705.   InitializeStats();
  706.   UpdateDisplay(0,0,1,0);
  707.   Sdepth = 0;
  708. }
  709.  
  710.  
  711. SaveGame()
  712. {
  713. FILE *fd;
  714. char fname[40];
  715. short sq,i,c;
  716.  
  717.   ShowMessage("File name: ");
  718.   scanz("%s",fname);
  719.   
  720.   if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000");
  721.   fd = fopen(fname,"w");
  722.   fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50);
  723.   fprintf(fd,"%d %d %d %d\n",
  724.           castld[white],castld[black],kingmoved[white],kingmoved[black]);
  725.   fprintf(fd,"%d %d\n",TCflag,OperatorTime);
  726.   fprintf(fd,"%ld %ld %d %d\n",
  727.           TimeControl.clock[white],TimeControl.clock[black],
  728.           TimeControl.moves[white],TimeControl.moves[black]);
  729.   for (sq = 0; sq < 64; sq++)
  730.     {
  731.       if (color[sq] == neutral) c = 0; else c = color[sq]+1;
  732.       fprintf(fd,"%d\n",256*board[sq] + c);
  733.     }
  734.   for (i = 0; i <= GameCnt; i++)
  735.     {
  736.       if (GameList[i].color == neutral) c = 0;
  737.       else c = GameList[i].color + 1;
  738.       fprintf(fd,"%d %d %d %ld %d %d %d\n",
  739.               GameList[i].gmove,GameList[i].score,GameList[i].depth,
  740.               GameList[i].nodes,GameList[i].time,
  741.               GameList[i].piece,c);
  742.     }
  743.   fclose(fd);
  744. }
  745.  
  746.  
  747. ListGame()
  748. {
  749. FILE *fd;
  750. short i,f,t;
  751.   fd = fopen("chess.lst","w");
  752.   fprintf(fd,"\n");
  753.   fprintf(fd,"       score  depth  nodes  time         ");
  754.   fprintf(fd,"       score  depth  nodes  time\n");
  755.   for (i = 0; i <= GameCnt; i++)
  756.     {
  757.       f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF);
  758.       algbr(f,t,false);
  759.       if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd,"         ");
  760.       fprintf(fd,"%5s  %5d     %2d %6ld %5d",mvstr1,
  761.               GameList[i].score,GameList[i].depth,
  762.               GameList[i].nodes,GameList[i].time);
  763.     }
  764.   fprintf(fd,"\n\n");
  765.   fclose(fd);
  766.  
  767.  
  768. Undo()
  769.  
  770. /*
  771.    Undo the most recent half-move.
  772. */
  773.  
  774. {
  775. short f,t;
  776.   f = GameList[GameCnt].gmove>>8;
  777.   t = GameList[GameCnt].gmove & 0xFF;
  778.   if (board[t] == king && distance(t,f) > 1)
  779.     castle(GameList[GameCnt].color,f,t,2);
  780.   else
  781.     {
  782.       board[f] = board[t]; color[f] = color[t];
  783.       board[t] = GameList[GameCnt].piece;
  784.       color[t] = GameList[GameCnt].color;
  785.       if (board[f] == king) --kingmoved[color[f]];
  786.     }
  787.   if (TCflag) ++TimeControl.moves[color[f]];
  788.   GameCnt--; mate = false; Sdepth = 0;
  789.   UpdateDisplay(0,0,1,0);
  790.   InitializeStats();
  791. }
  792.  
  793.  
  794. ShowMessage(s)
  795. char *s;
  796. {
  797.   gotoXY(50,24); printz("%s",s); ClrEoln();
  798. }
  799.  
  800. ClearMessage()
  801. {
  802.   gotoXY(50,24); ClrEoln();
  803. }
  804.  
  805. ShowSidetomove()
  806. {
  807.   gotoXY(50,14);
  808.   if (player == white) printz("%2d:   WHITE",1+(GameCnt+1)/2);
  809.   else printz("%2d:   BLACK",1+(GameCnt+1)/2);
  810.   ClrEoln();
  811. }
  812.  
  813. PromptForMove()
  814. {
  815.   gotoXY(50,19); printz("Your move is? "); ClrEoln();
  816. }
  817.  
  818. ShowCurrentMove(pnt,f,t)
  819. short pnt,f,t;
  820. {
  821.   if (post && player == computer)
  822.     {
  823.       algbr(f,t,false);
  824.       gotoXY(50,7); printz("(%2d) %4s",pnt,mvstr1);
  825.     }
  826. }
  827.  
  828. ChangeAlphaWindow()
  829. {
  830.   ShowMessage("window: ");
  831.   scanz("%hd",&Awindow);
  832. }
  833.  
  834. ChangeBetaWindow()
  835. {
  836.   ShowMessage("window: ");
  837.   scanz("%hd",&Bwindow);
  838. }
  839.  
  840. GiveHint()
  841. {
  842. char s[40];
  843.   algbr((short)(hint>>8),(short)(hint & 0xFF),false);
  844.   strcpy(s,"try ");
  845.   strcat(s,mvstr1);
  846.   ShowMessage(s);
  847. }
  848.  
  849. ChangeSearchDepth()
  850. {
  851.   ShowMessage("depth= ");
  852.   scanz("%hd",&MaxSearchDepth);
  853. }
  854.  
  855. SetContempt()
  856. {
  857.   ShowMessage("contempt= ");
  858.   scanz("%hd",&contempt);
  859. }
  860.  
  861. ChangeXwindow()
  862. {
  863.   ShowMessage("xwndw= ");
  864.   scanz("%hd",&xwndw);
  865. }
  866.  
  867.  
  868. SelectLevel()
  869. {
  870.   ClrScreen();
  871.   gotoXY(32,2); printz("CHESS");
  872.   gotoXY(20,4); printz(" 1.   60 moves in   5 minutes");
  873.   gotoXY(20,5); printz(" 2.   60 moves in  15 minutes");
  874.   gotoXY(20,6); printz(" 3.   60 moves in  30 minutes");
  875.   gotoXY(20,7); printz(" 4.   40 moves in  30 minutes");
  876.   gotoXY(20,8); printz(" 5.   40 moves in  60 minutes");
  877.   gotoXY(20,9); printz(" 6.   40 moves in 120 minutes");
  878.   gotoXY(20,10); printz(" 7.   40 moves in 240 minutes");
  879.   gotoXY(20,11); printz(" 8.    1 move  in  15 minutes");
  880.   gotoXY(20,12); printz(" 9.    1 move  in  60 minutes");
  881.   gotoXY(20,13); printz("10.    1 move  in 600 minutes");
  882.   
  883.   OperatorTime = 0; TCmoves = 60; TCminutes = 5;
  884.   gotoXY(20,17); printz("Enter Level: ");
  885.   refresh();
  886.   scanz("%ld",&Level);
  887.   switch (Level)
  888.     {
  889.       case 1 : TCmoves = 60; TCminutes = 5; break;
  890.       case 2 : TCmoves = 60; TCminutes = 15; break;
  891.       case 3 : TCmoves = 60; TCminutes = 30; break;
  892.       case 4 : TCmoves = 40; TCminutes = 30; break;
  893.       case 5 : TCmoves = 40; TCminutes = 60; break;
  894.       case 6 : TCmoves = 40; TCminutes = 120; break;
  895.       case 7 : TCmoves = 40; TCminutes = 240; break;
  896.       case 8 : TCmoves = 1; TCminutes = 15; break;
  897.       case 9 : TCmoves = 1; TCminutes = 60; break;
  898.       case 10 : TCmoves = 1; TCminutes = 600; break;
  899.     }
  900.   TCflag = (TCmoves > 1);
  901.   SetTimeControl();
  902.   ClrScreen();
  903.   UpdateDisplay(0,0,1,0);
  904. }
  905.  
  906.  
  907. ShowPostnValues()
  908. {
  909. short i,r,c;
  910.   ExaminePosition();
  911.   for (i = 0; i < 64; i++)
  912.     {
  913.       if (reverse) r = 7-row[i]; else r = row[i];
  914.       if (reverse) c = 7-column[i]; else c = column[i];
  915.       gotoXY(4+5*c,5+2*(7-r));
  916.       c1 = color[i]; c2 = otherside[c1];
  917.       PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
  918.       atk1 = atak[c1]; atk2 = atak[c2];
  919.       if (color[i] == neutral) printz("   ");
  920.       else printz("%3d ",SqValue(i,opponent));
  921.     }
  922.   ScorePosition(opponent,&i);
  923.   gotoXY(50,24);
  924.   printz("Score= %d",i); ClrEoln();
  925. }
  926.  
  927.  
  928. DoDebug()
  929. {
  930. short k,p,i,r,c,tp,tc;
  931. char s[40];
  932.   ExaminePosition();
  933.   ShowMessage("Enter piece: ");
  934.   scanz("%s",s);
  935.   if (s[0] == 'w') k = white; else k = black;
  936.   if (s[1] == 'p') p = pawn;
  937.   else if (s[1] == 'n') p = knight;
  938.   else if (s[1] == 'b') p = bishop;
  939.   else if (s[1] == 'r') p = rook;
  940.   else if (s[1] == 'q') p = queen;
  941.   else if (s[1] == 'k') p = king;
  942.   else p = no_piece;
  943.   for (i = 0; i < 64; i++)
  944.     {
  945.       if (reverse) r = 7-row[i]; else r = row[i];
  946.       if (reverse) c = 7-column[i]; else c = column[i];
  947.       gotoXY(4+5*c,5+2*(7-r));
  948.       tp = board[i]; tc = color[i];
  949.       board[i] = p; color[i] = k;
  950.       c1 = k; c2 = otherside[c1];
  951.       PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
  952.       atk1 = atak[c1]; atk2 = atak[c2];
  953.       printz("%3d ",SqValue(i,opponent));
  954.       board[i] = tp; color[i] = tc;
  955.     }
  956.   ScorePosition(opponent,&i);
  957.   gotoXY(50,24);
  958.   printz("Score= %d",i); ClrEoln();
  959. }
  960.